package jaux.tank.service.system.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import jaux.tank.bean.entity.system.Menu;
import jaux.tank.bean.enumeration.BizExceptionEnum;
import jaux.tank.bean.exception.TankException;
import jaux.tank.bean.vo.node.MenuNode;
import jaux.tank.bean.vo.node.Node;
import jaux.tank.bean.vo.node.ZTreeNode;
import jaux.tank.dao.system.MenuRepository;
import jaux.tank.service.system.MenuService;
import jaux.tank.utils.Lists;
import jaux.tank.utils.ToolUtil;

/**
 * Created  on 2018/3/23 0023.
 *
 */
@Service
public class MenuServiceImpl implements MenuService {
    private Logger logger = LoggerFactory.getLogger(MenuServiceImpl.class);
    @Autowired
    private MenuRepository menuRepository;


    @Override
    public void delMenu(String menuId) {
        //删除菜单
        this.menuRepository.deleteById(menuId);
        //删除关联的relation
        this.menuRepository.deleteRelationByMenu(menuId);

    }

    @Override
    public void delMenuContainSubMenus(String menuId) {
        menuRepository.findById(menuId).ifPresent(menu->{
        	
        	//删除所有子菜单
        	List<Menu> menus = menuRepository.findByPcodesLike("%[" + menu.getCode() + "]%");
        	menuRepository.deleteAll(menus);
        	//删除当前菜单
        	delMenu(menuId);
        });

    }
    @Override
    public List<MenuNode> getMenusByRoleIds(List<String> roleList) {
        List menus = menuRepository.getMenusByRoleIds(roleList);
       return transferMenuNode(menus);

    }

    @Override
    public List<MenuNode> getMenusTreeByRoleIds(List<String> roleList) {
        List menus = menuRepository.getMenusByRoleIds(roleList);
        List<MenuNode> result =  generateTree(transferMenuNode(menus));
        for(MenuNode menuNode:result){
            if(!menuNode.getChildren().isEmpty()){
                sortTree(menuNode.getChildren());
                for(MenuNode menuNode1: menuNode.getChildren()){
                    if(!menuNode1.getChildren().isEmpty()) {
                        sortTree(menuNode1.getChildren());
                    }
                }
            }
        }
        sortTree(result);
        return result;
    }

    @Override
    public List<MenuNode> getMenus() {
        List<MenuNode> list =  transferMenuNode(menuRepository.getMenus());
        List<MenuNode> result =  generateTree(list);


        for(MenuNode menuNode:result){
            if(!menuNode.getChildren().isEmpty()){
                sortTree(menuNode.getChildren());
                for(MenuNode menuNode1: menuNode.getChildren()){
                    if(!menuNode1.getChildren().isEmpty()) {
                        sortTree(menuNode1.getChildren());
                    }
                }
            }
        }
        sortTree(result);
        return result;
    }
    private void sortTree(List<MenuNode> list){
        Collections.sort(list, new Comparator<MenuNode>() {
            @Override
            public int compare(MenuNode o1, MenuNode o2) {
            	if(o1==null ||o1.getNum()==null)
            		return -1;
            	if(o2==null ||o2.getNum()==null)
            		return 1;
                return o1.getNum()-o2.getNum();
            }
        });
    }
    private List<MenuNode> generateTree(List<MenuNode> list){
        List<MenuNode> result = new ArrayList<>(20);
        Map<String,MenuNode> map = Lists.toMap(list,"id");
        for(Map.Entry<String,MenuNode> entry:map.entrySet()){
            MenuNode menuNode = entry.getValue();

            if(!"0".equals(menuNode.getParentId())){
                MenuNode parentNode = map.get(menuNode.getParentId());
                parentNode.getChildren().add(menuNode);
            }else{
                result.add(menuNode);
            }
        }
        return result;

    }
    private List<MenuNode> transferMenuNode(List menus){
        List<MenuNode> menuNodes = new ArrayList<>();
        try {
            for(int i=0;i<menus.size();i++){
                Object[] source = (Object[]) menus.get(i);
                MenuNode menuNode = new MenuNode();
                menuNode.setId(source[0].toString());
                menuNode.setIcon(String.valueOf(source[1]));
                menuNode.setParentId(source[2].toString());
                menuNode.setName(String.valueOf(source[3]));
                menuNode.setUrl(String.valueOf(source[4]));
                menuNode.setLevels(Integer.valueOf(source[5].toString()));
                menuNode.setIsmenu(Integer.valueOf(source[6].toString()));
                menuNode.setNum(Integer.valueOf(source[7].toString()));
                menuNode.setCode(String.valueOf(source[8]));
                menuNode.setStatus(Integer.valueOf(source[9].toString()));
                menuNodes.add(menuNode);

            }
        }catch (Exception e){
            logger.error(e.getMessage(),e);
        }
        return menuNodes;
    }
    @Override
    public List<ZTreeNode> menuTreeList() {
        List list = menuRepository.menuTreeList();
        List<ZTreeNode> nodes  =new ArrayList<>();
        for(int i=0;i<list.size();i++){
           Object[] source = (Object[]) list.get(i);
            ZTreeNode node = new ZTreeNode();
            node.setId(source[0].toString());
            node.setpId(source[1].toString());
            node.setName(source[2].toString());
            node.setIsOpen(Boolean.valueOf(source[3].toString()));
            Map<String,String> nodeData = new HashMap<>();
            nodeData.put("code", source[4].toString());
            node.setNodeData(nodeData);
            nodes.add(node);
        }
        return nodes;
    }

    @Override
    public List<ZTreeNode> menuTreeListByMenuIds(List<String> menuIds) {
        List list = menuRepository.menuTreeListByMenuIds(menuIds);
        List<ZTreeNode> nodes  =new ArrayList<>();
        for(int i=0;i<list.size();i++){
            Object[] source = (Object[]) list.get(i);
            ZTreeNode node = new ZTreeNode();
            node.setId(source[0].toString());
            node.setpId(source[1].toString());
            node.setName(source[2].toString());
            node.setIsOpen(Boolean.valueOf(source[3].toString()));
            node.setChecked(Boolean.valueOf(source[4].toString()));
            nodes.add(node);
        }
        return nodes;
    }

    @Override
    public void menuSetPcode(Menu menu) {
        if (ToolUtil.isEmpty(menu.getPcode()) || menu.getPcode().equals("0")) {
            menu.setPcode("0");
            menu.setPcodes("[0],");
            menu.setLevels(1);
        } else {

            Menu pMenu = menuRepository.findByCode(menu.getPcode());
            Integer pLevels = pMenu.getLevels();
            menu.setPcode(pMenu.getCode());

            //如果编号和父编号一致会导致无限递归
            if (menu.getCode().equals(menu.getPcode())) {
                throw new TankException(BizExceptionEnum.MENU_PCODE_COINCIDENCE);
            }

            menu.setLevels(pLevels + 1);
            menu.setPcodes(pMenu.getPcodes() + "[" + pMenu.getCode() + "],");
        }
    }

    @Override
    public List<Node> generateMenuTreeForRole(List<ZTreeNode> list){

        List<Node> nodes = new ArrayList<>(20);
        for(ZTreeNode menu:list){
            Node permissionNode = new Node();
            permissionNode.setId(menu.getId());
            permissionNode.setName(menu.getName());
            permissionNode.setPid(menu.getpId());
            permissionNode.setChecked(menu.getChecked());
            nodes.add(permissionNode);
        }
        for(Node permissionNode:nodes){
            for(Node child:nodes){
                if(child.getPid().equals(permissionNode.getId())){
                    permissionNode.getChildren().add(child);
                }
            }
        }
        List<Node> result = new ArrayList<>(20);
        for(Node node:nodes){
            if("0".equals(node.getPid())){
                result.add(node);
            }
        }
        return result;


    }
}
